home *** CD-ROM | disk | FTP | other *** search
/ Openstep 4.2 (Developer) / Openstep Developer 4.2.iso / NextDeveloper / Source / GNU / uucp / Uucp.framework / unix.subproj / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-09  |  7.1 KB  |  295 lines

  1. /* pipe.c
  2.    The pipe port communication routines for Unix.
  3.    Contributed by Marc Boucher <marc@CAM.ORG>.
  4.  
  5.    Copyright (C) 1993 Ian Lance Taylor
  6.  
  7.    This file is part of the Taylor UUCP package.
  8.  
  9.    This program is free software; you can redistribute it and/or
  10.    modify it under the terms of the GNU General Public License as
  11.    published by the Free Software Foundation; either version 2 of the
  12.    License, or (at your option) any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful, but
  15.    WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.    General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.  
  23.    The author of the program may be contacted at ian@airs.com or
  24.    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
  25.    */
  26.  
  27. #include "uucp.h"
  28.  
  29. #if USE_RCS_ID
  30. const char pipe_rcsid[] = "$Id: pipe.c,v 1.6 1995/06/21 19:19:57 ian Rel $";
  31. #endif
  32.  
  33. #include "uudefs.h"
  34. #include "uuconf.h"
  35. #include "system.h"
  36. #include "conn.h"
  37. #include "sysdep.h"
  38.  
  39. #include <errno.h>
  40.  
  41. #if HAVE_FCNTL_H
  42. #include <fcntl.h>
  43. #else
  44. #if HAVE_SYS_FILE_H
  45. #include <sys/file.h>
  46. #endif
  47. #endif
  48.  
  49. /* Local functions.  */
  50.  
  51. static void uspipe_free P((struct sconnection *qconn));
  52. static boolean fspipe_open P((struct sconnection *qconn, long ibaud,
  53.                   boolean fwait));
  54. static boolean fspipe_close P((struct sconnection *qconn,
  55.                    pointer puuconf,
  56.                    struct uuconf_dialer *qdialer,
  57.                    boolean fsuccess));
  58. static boolean fspipe_dial P((struct sconnection *qconn, pointer puuconf,
  59.                   const struct uuconf_system *qsys,
  60.                   const char *zphone,
  61.                   struct uuconf_dialer *qdialer,
  62.                   enum tdialerfound *ptdialer));
  63.  
  64. /* The command table for standard input ports.  */
  65.  
  66. static const struct sconncmds spipecmds =
  67. {
  68.   uspipe_free,
  69.   NULL, /* pflock */
  70.   NULL, /* pfunlock */
  71.   fspipe_open,
  72.   fspipe_close,
  73.   fspipe_dial,
  74.   fsdouble_read,
  75.   fsdouble_write,
  76.   fsysdep_conn_io,
  77.   NULL, /* pfbreak */
  78.   NULL, /* pfset */
  79.   NULL, /* pfcarrier */
  80.   fsdouble_chat,
  81.   NULL  /* pibaud */
  82. };
  83.  
  84. /* Initialize a pipe connection.  */
  85.  
  86. boolean
  87. fsysdep_pipe_init (qconn)
  88.      struct sconnection *qconn;
  89. {
  90.   struct ssysdep_conn *q;
  91.  
  92.   q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
  93.   q->o = -1;
  94.   q->ord = -1;
  95.   q->owr = -1;
  96.   q->zdevice = NULL;
  97.   q->iflags = -1;
  98.   q->iwr_flags = -1;
  99.   q->fterminal = FALSE;
  100.   q->ftli = FALSE;
  101.   q->ibaud = 0;
  102.   q->ipid = -1;
  103.   qconn->psysdep = (pointer) q;
  104.   qconn->qcmds = &spipecmds;
  105.   return TRUE;
  106. }
  107.  
  108. static void
  109. uspipe_free (qconn)
  110.      struct sconnection *qconn;
  111. {
  112.   xfree (qconn->psysdep);
  113. }
  114.  
  115. /* Open a pipe port.  */
  116.  
  117. /*ARGSUSED*/
  118. static boolean
  119. fspipe_open (qconn, ibaud, fwait)
  120.      struct sconnection *qconn;
  121.      long ibaud;
  122.      boolean fwait;
  123. {
  124.   /* We don't do incoming waits on pipes.  */
  125.   if (fwait)
  126.     return FALSE;
  127.  
  128.   return TRUE;
  129. }
  130.  
  131. /* Close a pipe port.  */
  132.  
  133. /*ARGSUSED*/
  134. static boolean
  135. fspipe_close (qconn, puuconf, qdialer, fsuccess)
  136.      struct sconnection *qconn;
  137.      pointer puuconf;
  138.      struct uuconf_dialer *qdialer;
  139.      boolean fsuccess;
  140. {
  141.   struct ssysdep_conn *qsysdep;
  142.   boolean fret;
  143.  
  144.   qsysdep = (struct ssysdep_conn *) qconn->psysdep;
  145.   fret = TRUE;
  146.  
  147.   /* Close our sides of the pipe.  */
  148.   if (qsysdep->ord >= 0 && close (qsysdep->ord) < 0)
  149.     {
  150.       ulog (LOG_ERROR, "fspipe_close: close read fd: %s", strerror (errno));
  151.       fret = FALSE;
  152.     }
  153.   if (qsysdep->owr != qsysdep->ord
  154.       && qsysdep->owr >= 0
  155.       && close (qsysdep->owr) < 0)
  156.     {
  157.       ulog (LOG_ERROR, "fspipe_close: close write fd: %s", strerror (errno));
  158.       fret = FALSE;
  159.     }
  160.   qsysdep->ord = -1;
  161.   qsysdep->owr = -1;
  162.  
  163.   /* Kill dangling child process.  */
  164.   if (qsysdep->ipid >= 0)
  165.     {
  166.       if (kill (qsysdep->ipid, SIGHUP) == 0)
  167.         usysdep_sleep (2);
  168. #ifdef SIGPIPE
  169.       if (kill (qsysdep->ipid, SIGPIPE) == 0)
  170.         usysdep_sleep (2);
  171. #endif
  172.       if (kill (qsysdep->ipid, SIGKILL) < 0 && errno == EPERM)
  173.     {
  174.       ulog (LOG_ERROR, "fspipe_close: Cannot kill child pid %lu: %s",
  175.         (unsigned long) qsysdep->ipid, strerror (errno));
  176.       fret = FALSE;
  177.     }
  178.       else
  179.     (void) ixswait ((unsigned long) qsysdep->ipid, (const char *) NULL);
  180.     }
  181.   qsysdep->ipid = -1;
  182.   return fret;
  183. }
  184.  
  185. /* Dial out on a pipe port, so to speak: launch connection program
  186.    under us.  The code alternates q->o between q->ord and q->owr as
  187.    appropriate.  It is always q->ord before any call to fsblock.  */
  188.  
  189. /*ARGSUSED*/
  190. static boolean
  191. fspipe_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
  192.      struct sconnection *qconn;
  193.      pointer puuconf;
  194.      const struct uuconf_system *qsys;
  195.      const char *zphone;
  196.      struct uuconf_dialer *qdialer;
  197.      enum tdialerfound *ptdialer;
  198. {
  199.   struct ssysdep_conn *q;
  200.   int aidescs[3];
  201.   const char **pzprog;
  202.  
  203.   q = (struct ssysdep_conn *) qconn->psysdep;
  204.  
  205.   *ptdialer = DIALERFOUND_FALSE;
  206.  
  207.   pzprog = (const char **) qconn->qport->uuconf_u.uuconf_spipe.uuconf_pzcmd;
  208.  
  209.   if (pzprog == NULL)
  210.     {
  211.       ulog (LOG_ERROR, "No command for pipe connection");
  212.       return FALSE;
  213.     }
  214.  
  215.   aidescs[0] = SPAWN_WRITE_PIPE;
  216.   aidescs[1] = SPAWN_READ_PIPE;
  217.   aidescs[2] = SPAWN_NULL;
  218.  
  219.   /* Pass fkeepuid, fkeepenv and fshell as TRUE.  This puts the
  220.      responsibility of security on the connection program.  */
  221.   q->ipid = ixsspawn (pzprog, aidescs, TRUE, TRUE, (const char *) NULL,
  222.               FALSE, TRUE, (const char *) NULL,
  223.               (const char *) NULL, (const char *) NULL);
  224.   if (q->ipid < 0)
  225.     {
  226.       ulog (LOG_ERROR, "ixsspawn (%s): %s", pzprog[0], strerror (errno));
  227.       return FALSE;
  228.     }
  229.  
  230.   q->owr = aidescs[0];
  231.   q->ord = aidescs[1];
  232.   q->o = q->ord;
  233.  
  234.   q->iflags = fcntl (q->ord, F_GETFL, 0);
  235.   q->iwr_flags = fcntl (q->owr, F_GETFL, 0);
  236.   if (q->iflags < 0 || q->iwr_flags < 0)
  237.     {
  238.       ulog (LOG_ERROR, "fspipe_dial: fcntl: %s", strerror (errno));
  239.       (void) fspipe_close (qconn, puuconf, qdialer, FALSE);
  240.       return FALSE;
  241.     }
  242.  
  243.   return TRUE;
  244. }
  245.  
  246. #if 0
  247.  
  248. /* Marc Boucher's contributed code used an alarm to avoid waiting too
  249.    long when closing the pipe.  However, I believe that it is not
  250.    possible for the kernel to sleep when closing a pipe; it is only
  251.    possible when closing a device.  Therefore, I have removed the
  252.    code, but am preserving it in case I am wrong.  To reenable it, the
  253.    two calls to close in fspipe_close should be changed to call
  254.    fspipe_alarmclose.  */
  255.  
  256. static RETSIGTYPE
  257. usalarm (isig)
  258.      int isig;
  259. {
  260. #if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET
  261.   (void) signal (isig, usalarm);
  262. #endif
  263.  
  264. #if HAVE_RESTARTABLE_SYSCALLS
  265.   longjmp (sSjmp_buf, 1);
  266. #endif
  267. }
  268.  
  269. static int
  270. fspipe_alarmclose (fd)
  271.      int fd;
  272. {
  273.   int iret = -1;
  274.   int ierrno = 0;
  275.  
  276.   if (fsysdep_catch ())
  277.     {
  278.       usysdep_start_catch ();
  279.       usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL);
  280.       (void) alarm (30);
  281.  
  282.       iret = close (fd);
  283.       ierrno = errno;
  284.     }
  285.  
  286.   usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL);
  287.   (void) alarm (0);
  288.   usysdep_end_catch ();
  289.  
  290.   errno = ierrno;
  291.   return iret;
  292. }
  293.  
  294. #endif /* 0 */
  295.